import 'dart:convert';
import 'package:app_router_demo/config/app_config.dart';
import 'package:app_router_demo/services/api_response.dart';
import 'package:app_router_demo/utils/validators.dart';
import 'package:dio/dio.dart';
import 'package:flutter/foundation.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:pretty_dio_logger/pretty_dio_logger.dart';

/// HTTP服务类，封装网络请求相关功能
class HttpService {
  static final HttpService _instance = HttpService._internal();
  late final Dio _dio;
  bool _isInitialized = false; // 新增：标记是否已初始化

  // 单例模式
  factory HttpService() => _instance;

  HttpService._internal() {
    _dio = Dio();
    // 构造函数不再直接调用 _initDio，改为通过公共的 initialize 方法
  }

  /// 初始化Dio配置
  /// 必须在使用 HttpService 实例之前调用此方法，并等待其完成
  Future<void> initialize() async {
    if (_isInitialized) return; // 避免重复初始化

    // 获取 PackageInfo 和 DeviceInfo 一次性
    final packageInfo = await PackageInfo.fromPlatform();
    final deviceInfo = await _getDeviceInfo(packageInfo); // 传递 packageInfo

    // 设置基础URL，根据环境配置选择
    _dio.options.baseUrl = AppConfig.baseUrl;

    // 设置连接超时时间
    _dio.options.connectTimeout = const Duration(seconds: 15);
    _dio.options.receiveTimeout = const Duration(seconds: 15);

    // 设置请求头
    _setHeaders(deviceInfo, packageInfo); // 传递已获取的信息

    // 添加拦截器
    _addInterceptors();

    _isInitialized = true; // 标记为已初始化
  }

  /// 设置请求头，包含设备信息等
  /// 接收预先获取的设备信息和包信息
  void _setHeaders(Map<String, String> deviceInfo, PackageInfo packageInfo) {
    // 构建User-Agent
    final userAgent =
        '${packageInfo.appName}/${packageInfo.version} '
        '(${deviceInfo['system']} ${deviceInfo['systemVersion']}; '
        '${deviceInfo['deviceModel']})';

    // 设置通用请求头
    _dio.options.headers.addAll({
      'Content-Type': 'application/json',
      'accept-language': 'zh-CN',
      'version': packageInfo.version, // 使用实际应用版本
      'osappversion': packageInfo.version,
      'system': deviceInfo['system'],
      'system-version': deviceInfo['systemVersion'],
      'device-model': deviceInfo['deviceModel'],
      'bundleID': packageInfo.packageName,
      'User-Agent': userAgent,
      'CHANNEL': 'official',
      'device-id': deviceInfo['deviceId'],
      'app_code': 'app_code',
      // TODO: accessToken 应通过登录流程动态获取并设置，不应硬编码
      'accessToken':
          '1914954201131405314_USER&API&86b3f21491a7a681a21a92a29eeb794917d3156cfa4ecf2a4123703e22faabab',
    });
  }

  /// 获取设备信息
  /// 接收 packageInfo 以获取 appVersion
  Future<Map<String, String>> _getDeviceInfo(PackageInfo packageInfo) async {
    final deviceInfoPlugin = DeviceInfoPlugin();
    final Map<String, String> deviceData = <String, String>{};

    try {
      if (defaultTargetPlatform == TargetPlatform.android) {
        final androidInfo = await deviceInfoPlugin.androidInfo;
        deviceData['system'] = 'Android';
        deviceData['systemVersion'] = androidInfo.version.release;
        deviceData['deviceModel'] = androidInfo.model;
        deviceData['deviceId'] = androidInfo.id;
        deviceData['appVersion'] = packageInfo.version; // 从 PackageInfo 获取
      } else if (defaultTargetPlatform == TargetPlatform.iOS) {
        final iosInfo = await deviceInfoPlugin.iosInfo;
        deviceData['system'] = 'iOS';
        deviceData['systemVersion'] = iosInfo.systemVersion ?? '';
        deviceData['deviceModel'] = iosInfo.model ?? '';
        deviceData['deviceId'] = iosInfo.identifierForVendor ?? '';
        deviceData['appVersion'] = packageInfo.version; // 从 PackageInfo 获取
      }
    } catch (e) {
      debugPrint('获取设备信息失败: $e');
      // 提供默认值
      deviceData['system'] = defaultTargetPlatform.toString();
      deviceData['systemVersion'] = 'unknown';
      deviceData['deviceModel'] = 'unknown';
      deviceData['deviceId'] = 'unknown';
      deviceData['appVersion'] =
          packageInfo.version; // 即使出错也尝试用 PackageInfo 的版本
    }

    return deviceData;
  }

  /// 添加拦截器
  void _addInterceptors() {
    // 添加日志拦截器 - 使用 PrettyDioLogger 替代原有的 LogInterceptor
    _dio.interceptors.add(
      PrettyDioLogger(
        requestHeader: true,
        requestBody: true,
        responseBody: true,
        responseHeader: false,
        error: true,
        compact: true,
        maxWidth: 120, // 增加 maxWidth 以显示更完整的响应内容
      ),
    );

    // 添加错误处理拦截器
    _dio.interceptors.add(
      InterceptorsWrapper(
        onRequest: (options, handler) {
          // 记录请求开始时间
          options.extra['startTime'] = DateTime.now().millisecondsSinceEpoch;
          debugPrint('🚀 开始请求: ${options.path}');
          return handler.next(options);
        },
        onResponse: (response, handler) {
          // 计算请求耗时
          final startTime = response.requestOptions.extra['startTime'] as int?;
          if (startTime != null) {
            final endTime = DateTime.now().millisecondsSinceEpoch;
            final duration = endTime - startTime;
            debugPrint(
              '✅ 请求成功: ${response.requestOptions.path} (耗时: ${duration}ms)',
            );
          }
          return handler.next(response);
        },
        onError: (DioException e, handler) {
          // 统一处理错误并记录日志
          final startTime = e.requestOptions.extra['startTime'] as int?;
          if (startTime != null) {
            final endTime = DateTime.now().millisecondsSinceEpoch;
            final duration = endTime - startTime;
            debugPrint('❌ 请求失败: ${e.requestOptions.path} (耗时: ${duration}ms)');
          }

          _logError(e);
          return handler.next(e);
        },
      ),
    );
  }

  /// 记录错误日志
  void _logError(DioException e) {
    final sb = StringBuffer();
    sb.writeln('请求错误详情:');
    sb.writeln('- URL: ${e.requestOptions.uri}');
    sb.writeln('- 方法: ${e.requestOptions.method}');
    sb.writeln('- 状态码: ${e.response?.statusCode}');
    sb.writeln('- 错误类型: ${e.type}');
    sb.writeln('- 错误信息: ${e.message}');

    if (e.response?.data != null) {
      // 尝试打印更清晰的响应数据
      try {
        sb.writeln('- 响应数据: ${jsonEncode(e.response?.data)}');
      } catch (encodeError) {
        sb.writeln('- 响应数据 (无法解析): ${e.response?.data}');
      }
    }

    debugPrint(sb.toString());
  }

  /// 设置访问令牌
  void setAccessToken(String token) {
    _dio.options.headers['accessToken'] = token;
  }

  /// 清除访问令牌
  void clearAccessToken() {
    _dio.options.headers.remove('accessToken');
  }

  /// 执行GET请求
  Future<ApiResponse<T>> get<T>(
    String path, {
    Map<String, dynamic>? queryParameters,
    Options? options,
    T? Function(dynamic)? fromJson,
    bool needDecrypt = true,
  }) async {
    try {
      final response = await _dio.get<String>(
        path,
        queryParameters: queryParameters,
        options: options ?? Options(responseType: ResponseType.plain),
      );

      return _handleResponse<T>(response, fromJson, needDecrypt);
    } on DioException catch (e) {
      return _handleError<T>(e);
    } catch (e) {
      // 捕获所有其他未知错误
      return ApiResponse<T>.failure(message: e.toString());
    }
  }

  /// 执行POST请求
  Future<ApiResponse<T>> post<T>(
    String path, {
    dynamic data,
    Map<String, dynamic>? queryParameters,
    Options? options,
    T? Function(dynamic)? fromJson,
    bool needDecrypt = true,
  }) async {
    try {
      String? encryptedDataString;
      if (data is Map<String, dynamic>) {
        final jsonString = json.encode(data);
        encryptedDataString = Validators().vhbsJiami(
          jsonString,
          AppConfig.encryptKey,
        );
        // 将加密后的字符串作为 Dio 的请求体数据
        data = encryptedDataString;
      }

      final response = await _dio.post<String>(
        path,
        data: data,
        queryParameters: queryParameters,
        options: options ?? Options(responseType: ResponseType.plain),
      );

      return _handleResponse<T>(response, fromJson, needDecrypt);
    } on DioException catch (e) {
      return _handleError<T>(e);
    } catch (e) {
      // 捕获所有其他未知错误
      return ApiResponse<T>.failure(message: e.toString());
    }
  }

  /// 处理响应数据 - **已根据你的反馈进行修改**
  ApiResponse<T> _handleResponse<T>(
    Response<String> response,
    T? Function(dynamic)? fromJson,
    bool needDecrypt,
  ) {
    try {
      String responseData = response.data ?? '';

      if (needDecrypt) {
        responseData = Validators().decryptVhbs(
          responseData,
          AppConfig.encryptKey,
        );
      }

      // 解析JSON
      final dynamic decodedJson = json.decode(responseData);

      debugPrint("decodedJson = $decodedJson");

      if (decodedJson is Map<String, dynamic>) {
        // 如果最外层是Map，直接使用它
        return ApiResponse<T>.fromJson(decodedJson, fromJson);
      } else if (decodedJson is List) {
        // 如果最外层是List (不常见，但为了兼容性保留，并将其包装成预期的Map结构)
        final wrappedData = {'code': 200, 'message': '成功', 'data': decodedJson};
        return ApiResponse<T>.fromJson(wrappedData, fromJson);
      } else {
        // 其他类型，包装成错误响应
        return ApiResponse<T>.failure(message: '服务器返回数据格式错误或未知类型');
      }
    } on FormatException catch (e) {
      debugPrint('JSON 解析失败: $e, 原始数据: ${response.data}');
      return ApiResponse<T>.failure(message: 'JSON 解析失败: $e');
    } catch (e) {
      debugPrint('处理响应数据失败: $e');
      return ApiResponse<T>.failure(message: '处理响应数据失败: $e');
    }
  }

  /// 处理错误
  ApiResponse<T> _handleError<T>(DioException e) {
    int finalCode = 500;
    String finalMessage = '未知错误';

    switch (e.type) {
      case DioExceptionType.connectionTimeout:
      case DioExceptionType.sendTimeout:
      case DioExceptionType.receiveTimeout:
        finalCode = 408;
        finalMessage = '请求超时';
        break;
      case DioExceptionType.badResponse:
        finalCode =
            e.response?.statusCode ?? 400; // 如果 statusCode 为 null，则使用 400
        if (e.response?.data != null) {
          try {
            final dynamic errorRawData = e.response?.data;
            Map<String, dynamic> errorData;

            if (errorRawData is String) {
              errorData = json.decode(errorRawData);
            } else if (errorRawData is Map<String, dynamic>) {
              errorData = errorRawData;
            } else {
              errorData = {};
            }

            if (errorData.containsKey('message') &&
                errorData['message'] is String) {
              finalMessage = errorData['message'];
            } else {
              finalMessage = '服务器响应错误: ${finalCode}';
            }
          } catch (_) {
            finalMessage = '服务器响应错误: ${finalCode}';
          }
        } else {
          finalMessage = '服务器响应错误: ${finalCode}';
        }
        break;
      case DioExceptionType.cancel:
        finalCode = 499;
        finalMessage = '请求被取消';
        break;
      case DioExceptionType.unknown:
      default:
        finalMessage = '网络错误: ${e.message ?? '未知错误'}';
        finalCode = 500;
        break;
    }
    return ApiResponse<T>.failure(code: finalCode, message: finalMessage);
  }
}

// 辅助函数 _processResponse 应该被移除或整合到 _handleResponse 中，因为它与 _handleResponse 功能重复
// 为了保持一致性，这里暂时将其保留，但建议在实际项目中去除冗余
ApiResponse<T> _processResponse<T>(
  Response response,
  T? Function(dynamic)? fromJson,
) {
  try {
    String responseData = response.data.toString();

    responseData = Validators().decryptVhbs(responseData, AppConfig.encryptKey);

    final jsonData = json.decode(responseData);

    if (jsonData is List) {
      final wrappedData = {'code': 200, 'message': '成功', 'data': jsonData};
      return ApiResponse<T>.fromJson(wrappedData, fromJson);
    } else if (jsonData is Map<String, dynamic>) {
      return ApiResponse<T>.fromJson(jsonData, fromJson);
    } else {
      return ApiResponse<T>.failure(message: '服务器返回数据格式错误');
    }
  } on FormatException catch (e) {
    debugPrint('JSON 解析失败: $e, 原始数据: ${response.data}');
    return ApiResponse<T>.failure(message: 'JSON 解析失败: $e');
  } catch (e) {
    debugPrint('处理响应数据失败: $e');
    return ApiResponse<T>.failure(message: '处理响应数据失败: $e');
  }
}
